package com.ledim.fragment.base;

import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import com.ledim.adapter.base.LedimBaseListAdapter;
import com.ledim.utils.ConstantUtil;
import com.ledim.utils.LedimNetWorkUtils;
import com.ledim.widget.loadmore.LoadMoreListViewContainer;
import com.ledim.widget.loadmore.LoadMoreStateCode;
import com.ledim.widget.ptr.LedimListViewStateView;
import com.ledim.widget.ptr.PtrClassicFrameLayout;
import com.ledim.widget.ptr.PtrDefaultHandler;
import com.ledim.widget.ptr.PtrFrameLayout;
import com.ledim.widget.ptr.PtrHandler;
import com.ledim.widget.ptr.header.LedimListViewHeader;
import com.letv.android.young.client.R;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by ccx on 16/5/20.
 */
public abstract class LedimBaseAdapterViewFragment<D, L extends AbsListView>
        extends LeDimBaseFragment implements LoadMoreStateCode {

    protected int mTotalPages = 0;// 总页数
    protected int mCurrPage = 0;// 当前页
    protected int mLoadPage = 0;// loading的页

    /**
     * 刷新还是加载更多 true： 刷新 ，false：上拉加载
     */
    protected boolean isPullRefresh = true;

    protected L mAdapterView;
    /**
     * 下拉刷新控件
     */
    protected PtrClassicFrameLayout mRefreshView;

    protected LoadMoreListViewContainer loadMoreContainer;
    /**
     * 各种状态的view，包括loading,server_error,no_net,no_data
     */
    protected LedimListViewStateView mLedimStateView;
    protected List<D> mItems = new ArrayList<D>();
    protected LedimBaseListAdapter<D> mAdapter;
    /**
     * TYPE_PULL_REFRESH 下拉刷新
     * TYPE_CLICK_STATEVIEW_REFRESH 点击中间stateview刷新
     */
    protected final static int TYPE_PULL_REFRESH = 0;
    protected final static int TYPE_CLICK_STATEVIEW_REFRESH = TYPE_PULL_REFRESH + 1;

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(getLayoutId(), container, false);
        mAdapterView = (L) view.findViewById(R.id.list);
        mAdapter = getAdapter();
        initFooterView(view);
        if (loadMoreContainer != null) {
            mAdapter.setOnScrollListener(loadMoreContainer);
        }
        mAdapterView.setAdapter(mAdapter);
        mAdapterView.setOnScrollListener(mAdapter);
        // 这里直接关联adapter与list, 刷新无需再调用adapter的 setDatas,只调用notify即可
        mAdapter.setInfos(mItems);

        mRefreshView = initRefreshView(view);
        mLedimStateView = (LedimListViewStateView) view.findViewById(R.id.state_view);
        mLedimStateView.setOnRetryListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                refresh(TYPE_CLICK_STATEVIEW_REFRESH);
                // autoRefresh();
            }
        });

        // 第一次进来时自动刷新
        //pullRefresh();
        refresh(TYPE_CLICK_STATEVIEW_REFRESH);
        initContentView(view, savedInstanceState);
        return view;
    }

    /**
     * 下拉刷新
     */
    protected void pullRefresh() {
        refresh(TYPE_PULL_REFRESH);
    }

    protected abstract LedimBaseListAdapter<D> getAdapter();

    // protected abstract L initAdapterView();

    /**
     * 发送请求，在这里调用mDataUtil的请求网络（推荐使用retri+okhttp在成功回调中调用setDatas方法）
     */
    protected abstract void getDatas();

    /**
     * 子类自定义的部分
     */
    protected void initFooterView(View view) {
    }

    protected void autoRefresh() {
        mRefreshView.autoRefresh(true);
    }

    protected final int getTotalPages(int totalNum) {
        if (totalNum <= getPageSize()) {
            return 1;
        }
        return totalNum % getPageSize() == 0 ? (totalNum / getPageSize())
                                             : (totalNum / getPageSize() + 1);
    }

    /**
     * 加载更多方法，有更多数据时才能调用
     */
    protected void loadMore() {
        isPullRefresh = false;
        // 如果loadmore的时候失败，但是mCurrPage已经++了
        mLoadPage++;
        getDatas();
    }

    /**
     * 仅仅是不使用hasmore字段的判断
     *
     * @return
     */
    private boolean hasMoreData() {
        return mLoadPage < mTotalPages;
    }

    /**
     * 刷新方法
     *
     * @param refreshType
     *         刷新类型
     *         下拉刷新 or 点击stateview刷新
     */
    protected void refresh(int refreshType) {
        isPullRefresh = true;
        mLoadPage = 0;
        mCurrPage = 0;
        mAdapterView.setSelection(0);
        if (refreshType == TYPE_PULL_REFRESH) {
            mLedimStateView.setState(LedimListViewStateView.STATE_OTHER);
        } else {
            mLedimStateView.setState(LedimListViewStateView.STATE_LOADING);
        }
        getDatas();
    }

    protected List<D> getItems() {
        return mItems;
    }

    /**
     * 服务器返回数据未成功
     */
    protected void setServerDataError() {
        if (isPullRefresh) {
            mItems.clear();
            if (mRefreshView.isRefreshing()) { // ptr的刷新
                mRefreshView.refreshComplete();
            } else {
                loadingClose();
            }
        }
        if (isPullRefresh) {
            if (!LedimNetWorkUtils.isNetworkAvailable(getBaseActivity())) {
                mLedimStateView.setState(LedimListViewStateView.STATE_NO_NET);
            } else {
                mLedimStateView.setState(LedimListViewStateView.STATE_SERVER_ERROR);
            }
            loadMoreFinish(STATE_REFRESH, false);
        } else { // 加载更多，证明已经有数据了，并不清空已有数据，不设置error状态
            mLoadPage = mCurrPage;
            // 如果loadmore的时候服务器拿不到数据，就认为hasMore=true
            loadMoreFinish(LedimNetWorkUtils.isNetworkAvailable(getBaseActivity()) ? ERROR_SE
                                                                                   : ERROR_NET, hasMoreData());
            mLedimStateView.setState(LedimListViewStateView.STATE_NORMAL);
        }

        mAdapter.notifyDataSetChanged();
    }

    /**
     * 如果使用服务器hasmore字段，就必须调用这个方法（推荐使用如果可以）
     *
     * @param list
     *         当数据异常得到的list为null时，setDatas(null)即可
     * @param hasMore
     *         是否有更多（来自服务器的字段）
     */
    protected void setDatas(List<D> list, boolean hasMore) {
        if (isPullRefresh) {
            mItems.clear();
            if (mRefreshView.isRefreshing()) { // ptr的刷新
                mRefreshView.refreshComplete();
            } else {
                loadingClose();
            }
        }
        if (list == null || list.isEmpty()) {
            if (isPullRefresh) {
                if (!LedimNetWorkUtils.isNetworkAvailable(getBaseActivity())) {
                    mLedimStateView.setState(LedimListViewStateView.STATE_NO_NET);
                } else {
                    mLedimStateView.setState(LedimListViewStateView.STATE_NO_DATA);
                }
                loadMoreFinish(STATE_REFRESH, false);
            } else { // 加载更多，证明已经有数据了，并不清空已有数据，不设置error状态
                mLoadPage = mCurrPage;
                // 如果loadmore的时候服务器拿不到数据，就认为hasMore=true
                loadMoreFinish(LedimNetWorkUtils.isNetworkAvailable(getBaseActivity()) ? ERROR_SE
                                                                                       : ERROR_NET, true);
                mLedimStateView.setState(LedimListViewStateView.STATE_NORMAL);
            }

        } else {
            mLedimStateView.setState(LedimListViewStateView.STATE_NORMAL);
            mItems.addAll(list);
            if (!isPullRefresh) {
                mCurrPage++;
            }
            loadMoreFinish(STATE_NORMAL, hasMore);
        }
        mAdapter.notifyDataSetChanged();
    }

    /**
     * @param errorCode
     *         -1表示unkonw错误，0表示正常，1表示网络异常，2表示服务器异常，等
     * @param hasMore
     */
    protected abstract void loadMoreFinish(int errorCode, boolean hasMore);

    /**
     * 使用loading 进行刷新，需要在结束后手动关闭
     */
    protected void loadingClose() {
        mLedimStateView.setState(LedimListViewStateView.STATE_NORMAL);
    }

    /**
     * @param totalPage
     */
    protected void setTotalPages(int totalPage) {
        mTotalPages = totalPage;
    }

    protected void initTotalPages(int totalNum) {
        mTotalPages = getTotalPages(totalNum);
    }

    protected int getPageSize() {
        return ConstantUtil.PAGE_SIZE;
    }

    protected final int getCurrPage() {
        return mCurrPage;
    }

    protected final int getLoadOffset() {
        return mLoadPage * getPageSize();
    }

    protected PtrClassicFrameLayout initRefreshView(View view) {
        PtrClassicFrameLayout ptr = (PtrClassicFrameLayout) view.findViewById(R.id.ptr_view);
        // 以下设置大都可在xml中设置
        // 设置阻尼系数
        // ptr.setResistance(1.7f);
        // // 触发刷新时移动的位置比例，默认，1.2f，移动达到头部高度 1.2 倍时可触发刷新操作。
        // // ptr.setRatioOfHeaderHeightToRefresh(1.2f);
        // // 回弹延时，默认 200ms，回弹到刷新高度所用时间
        // ptr.setDurationToClose(200);
        // // 头部回弹时间，默认 1000ms。
        // ptr.setDurationToCloseHeader(1000);
        // // 设置下拉达到高度后自动刷新（默认释放刷新）
        // ptr.setPullToRefresh(false);
        // // 刷新是否保持头部，默认值 true
        // ptr.setKeepHeaderWhenRefresh(true);
        // 自定义headerview
        ptr.setLoadingMinTime(2000);
        LedimListViewHeader header = new LedimListViewHeader(view.getContext());
        ptr.disableWhenHorizontalMove(true);
        ptr.setHeaderView(header);
        ptr.addPtrUIHandler(header);
        ptr.setPtrHandler(new PtrHandler() {
            @Override
            public boolean checkCanDoRefresh(PtrFrameLayout ptrFrameLayout, View view,
                                             View header) {
                return PtrDefaultHandler.checkContentCanBePulledDown(ptrFrameLayout, mAdapterView, header);
            }

            @Override
            public void onRefreshBegin(PtrFrameLayout ptrFrameLayout) {
                pullRefresh();
            }
        });
        return ptr;
    }

}
